package com.neuralnoise;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;

import com.neuralnoise.hibernate.HibernateSessionFactory;
import com.neuralnoise.hibernate.liveJournal.Interest;
import com.neuralnoise.hibernate.liveJournal.Journal;
import com.neuralnoise.hibernate.liveJournal.JournalDAO;
import com.neuralnoise.hibernate.liveJournal.Profile;
import com.neuralnoise.hibernate.liveJournal.ProfileDAO;

public class LiveJournalDB extends AbstractDB {

	private Logger logger = Logger.getLogger(this.getClass());
	
	private LiveJournalDB() { }
	
	public static void clean() {
		HibernateSessionFactory.getSession().beginTransaction();
		JournalDAO jdao = new JournalDAO();
		List<Journal> journals = jdao.findAll();
		for (Journal journal : journals) {
			jdao.delete(journal);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
	}

	public static Journal getJournal(String name) {
		HibernateSessionFactory.getSession().beginTransaction();
		JournalDAO jdao = new JournalDAO();
		Journal journal = jdao.findById(name);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return journal;
	}
	
	public static Collection<Journal> getJournals() {
		HibernateSessionFactory.getSession().beginTransaction();
		JournalDAO jdao = new JournalDAO();
		List<Journal> journals = jdao.findAll();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return journals;
	}
	
	public static Journal addJournal(String name) {
		HibernateSessionFactory.getSession().beginTransaction();
		JournalDAO jdao = new JournalDAO();
		Journal journal = new Journal(name);
		jdao.merge(journal);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return journal;
	}
	
	public static void delJournal(String name) {
		HibernateSessionFactory.getSession().beginTransaction();
		JournalDAO jdao = new JournalDAO();
		Journal j = jdao.findById(name);
		if (j != null) {
			jdao.delete(j);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
	}
	
	public static Journal toJournal(String name) {
		HibernateSessionFactory.getSession().beginTransaction();
		JournalDAO jdao = new JournalDAO();
		Journal journal = jdao.findById(name);
		if (journal == null) {
			journal = new Journal(name);
			jdao.merge(journal);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
		return journal;
	}
	
	public static Profile getProfile(String journal) {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();
		Profile profile = pdao.findById(journal);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return profile;
	}
	
	public static Collection<Profile> getProfiles() {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();
		Collection<Profile> profiles = pdao.findAll();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return profiles;
	}
	
	public static void addProfile(String journal, String foaf) {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();
		Profile p = new Profile(journal, foaf);
		pdao.merge(p);
		HibernateSessionFactory.getSession().getTransaction().commit();
	}

	public static Collection<Interest> getInterests(String name) {
		HibernateSessionFactory.getSession().beginTransaction();
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(Interest.class);
		criteria = criteria.createAlias("journals", "journals");
		criteria = criteria.add(Restrictions.eq("journals.id", name));
		Collection<Interest> interests = criteria.list();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return interests;
	}
	
	public static void addInterests(String name, Collection<Interest> interests) {
		HibernateSessionFactory.getSession().beginTransaction();
		JournalDAO jdao = new JournalDAO();
		Journal journal = jdao.findById(name);
		Set<Interest> jinterests = journal.getInterests();
		jinterests.addAll(interests);
		jdao.merge(journal);
		HibernateSessionFactory.getSession().getTransaction().commit();
	}
	
	public static Collection<Journal> getFriendsOf(String name) {
		HibernateSessionFactory.getSession().beginTransaction();
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(Journal.class);
		criteria = criteria.createAlias("journalsForSubject", "friendsOf");
		criteria = criteria.add(Restrictions.eq("friendsOf.id", name));
		Collection<Journal> friends = criteria.list();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return friends;
	}
	
	public static Collection<Journal> addFriendsOf(String name, Collection<String> friends) {
		Journal journal = toJournal(name);
		Collection<Journal> jfriends = new LinkedList<Journal>();
		for (String friend : friends) {
			jfriends.add(toJournal(friend));
		}
		HibernateSessionFactory.getSession().beginTransaction();
		JournalDAO jdao = new JournalDAO();
		for (Journal jfriend : jfriends) {
			journal.getJournalsForObject().add(jfriend);
			jdao.merge(journal);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
		return jfriends;
	}

	public static Journal addFriendsOf(String name, String friend) {
		Journal journal = toJournal(name);
		Journal jfriend = toJournal(friend);
		HibernateSessionFactory.getSession().beginTransaction();
		JournalDAO jdao = new JournalDAO();
		journal.getJournalsForObject().add(jfriend);
		jdao.merge(journal);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return jfriend;
	}
	
}
